home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 30
/
Aminet 30 (1999)(Schatztruhe)[!][Apr 1999].iso
/
Aminet
/
dev
/
lang
/
SmallEiffel.lha
/
SmallEiffel
/
lib_se
/
e_feature.e
< prev
next >
Wrap
Text File
|
1998-12-22
|
12KB
|
499 lines
-- This file is part of SmallEiffel The GNU Eiffel Compiler.
-- Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
-- Dominique COLNET and Suzanne COLLIN - colnet@loria.fr
-- http://www.loria.fr/SmallEiffel
-- SmallEiffel is free software; you can redistribute it and/or modify it
-- under the terms of the GNU General Public License as published by the Free
-- Software Foundation; either version 2, or (at your option) any later
-- version. SmallEiffel is distributed in the hope that it will be useful,but
-- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-- for more details. You should have received a copy of the GNU General
-- Public License along with SmallEiffel; see the file COPYING. If not,
-- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-- Boston, MA 02111-1307, USA.
--
deferred class E_FEATURE
--
-- For all possible Features : procedure, function, attribute,
-- constants, once procedure, once function, ...
--
inherit GLOBALS;
feature
base_class: BASE_CLASS;
-- The class where the feature is really written.
names: FEATURE_NAME_LIST;
-- All the names of the feature.
arguments: FORMAL_ARG_LIST is
-- Arguments if any.
deferred
end;
result_type: TYPE is
-- Result type if any.
deferred
end;
header_comment: COMMENT;
-- Header comment for a routine or following comment for
-- an attribute.
require_assertion: E_REQUIRE is
-- Not Void if any.
deferred
end;
ensure_assertion: E_ENSURE is
-- Not Void if any.
deferred
end;
local_vars: LOCAL_VAR_LIST;
-- Local var list if any.
clients: CLIENT_LIST;
-- Authorized clients list of the corresponding feature
-- clause in the base definition class.
is_deferred: BOOLEAN is
-- Is it a deferred feature ?
deferred
end;
frozen mapping_c_name_in(str: STRING) is
do
base_class.mapping_c_in(str);
str.append(first_name.to_key);
end;
frozen mapping_c_name is
local
s: STRING;
do
s := " ";
s.clear;
mapping_c_name_in(s);
cpp.put_string(s);
end;
base_class_name: CLASS_NAME is
-- Name of the class where the feature is really written.
do
Result := base_class.name;
end;
frozen first_name: FEATURE_NAME is
-- Return the principal (first) name of the feature.
do
Result := names.item(1);
ensure
Result /= void
end;
start_position: POSITION is
do
Result := first_name.start_position;
end;
to_run_feature(t: TYPE; fn: FEATURE_NAME): RUN_FEATURE is
-- If possible, gives the checked runnable feature for `t'.
-- Note: corresponding run_class dictionary is updated
-- with this new feature.
require
t.is_run_type;
fn /= Void;
deferred
ensure
Result /= Void implies t.run_class.at(fn) = Result;
Result = Void implies nb_errors > 0
end;
can_hide(other: E_FEATURE; rc: RUN_CLASS): BOOLEAN is
-- True when headings of Current can be hide with
-- heading of `other' in `rc'.
require
Current /= other;
do
if result_type /= other.result_type then
if result_type = Void or else other.result_type = Void then
eh.add_position(other.start_position);
error(start_position,"One has Result but not the other.");
end;
end;
if arguments /= other.arguments then
if arguments = Void or else other.arguments = Void then
eh.add_position(other.start_position);
error(start_position,"One has argument(s) but not the other.");
elseif arguments.count /= other.arguments.count then
eh.add_position(other.start_position);
error(start_position,"Incompatible number of arguments.");
end;
end;
if nb_errors = 0 then
if result_type /= Void then
if not result_type.is_a_in(other.result_type,rc) then
eh.append(em1);
eh.append(rc.current_type.run_time_mark);
eh.error(fz_dot);
end;
end;
end;
if nb_errors = 0 then
if arguments /= Void then
if not arguments.is_a_in(other.arguments,rc) then
eh.add_position(other.start_position);
eh.add_position(start_position)
eh.append(em1);
eh.append(rc.current_type.run_time_mark);
eh.error(fz_dot);
end;
end;
end;
Result := nb_errors = 0;
if Result then
merge_header_comments(other);
end;
end;
feature {PARENT_LIST}
frozen is_merge_with(other: E_FEATURE; rc: RUN_CLASS): BOOLEAN is
-- True when headings of Current can be merge with heading
-- of `other' in `rc'.
require
Current /= other;
eh.empty
do
Result := true;
if result_type /= other.result_type then
if result_type = Void or else other.result_type = Void then
Result := false;
end;
end;
if arguments /= other.arguments then
if arguments = Void or else other.arguments = Void then
Result := false;
elseif arguments.count /= other.arguments.count then
Result := false;
end;
end;
if Result then
if result_type /= Void then
Result := result_type.is_a_in(other.result_type,rc);
end;
if Result and then arguments /= Void then
Result := arguments.is_a_in(other.arguments,rc);
end;
if not Result then
Result := true;
eh.cancel;
if result_type /= Void then
Result := other.result_type.is_a_in(result_type,rc);
end;
if Result and then arguments /= Void then
Result := other.arguments.is_a_in(arguments,rc);
end;
end;
end;
if Result then
merge_header_comments(other);
end;
ensure
Result = eh.empty
end;
feature {PARENT}
frozen try_to_undefine(fn: FEATURE_NAME;
bc: BASE_CLASS): DEFERRED_ROUTINE is
-- When class `bc' has an undefine clause for `fn'.
-- Compute the corresponding undefined feature.
-- Check for (VDUS).
-- Not Void when no errors.
require
names.feature_name(fn.to_key) /= Void;
bc.name.is_subclass_of(base_class_name)
local
fn2: FEATURE_NAME;
do
-- For (VDUS) :
eh.add_position(fn.start_position);
fn2 := names.feature_name(fn.to_key);
if fn2 /= Void then
fn2.undefine_in(bc);
end;
eh.cancel;
--
Result := try_to_undefine_aux(fn,bc);
if Result /= Void then
Result.set_clients(clients);
merge_header_comments(Result);
else
bc.fatal_undefine(fn);
end;
ensure
Result /= Void
end;
feature {FEATURE_CLAUSE,E_FEATURE}
set_clients(c: like clients) is
require
c /= Void;
do
clients := c;
ensure
clients = c;
end;
feature
set_header_comment(hc: like header_comment) is
do
header_comment := hc;
end;
feature -- Pretty printing :
pretty_print is
require
fmt.indent_level = 1;
deferred
ensure
fmt.indent_level = 1;
end;
frozen pretty_print_profile is
do
pretty_print_names;
fmt.set_indent_level(2);
pretty_print_arguments;
fmt.set_indent_level(3);
if result_type /= Void then
fmt.put_string(": ");
result_type.pretty_print;
end;
end;
feature {RUN_FEATURE}
run_require(rf: RUN_FEATURE): RUN_REQUIRE is
-- Collect all (inherited) require assertions for
-- `rf'. Unless return Void (no assertion at all).
require
rf /= Void;
rf.base_feature = Current;
local
i: INTEGER;
r: like runnable;
er: E_REQUIRE;
hc: COMMENT;
ar: ARRAY[E_REQUIRE];
ct: TYPE;
do
require_collector.clear;
ct := rf.current_type;
ct.base_class.collect_for(code_require,rf.name);
if not require_collector.empty then
from
i := 1;
until
i > require_collector.upper
loop
er := require_collector.item(i);
hc := er.header_comment;
if not er.empty then
r := runnable(er.list,ct,rf);
if r /= Void then
!!er.make_runnable(r,ct,rf);
er.set_header_comment(hc);
if ar = Void then
ar := <<er>>;
else
ar.add_last(er);
end;
end;
end;
i := i + 1;
end;
if ar /= Void then
!!Result.make(ar);
end;
end;
end;
run_ensure(rf: RUN_FEATURE): E_ENSURE is
require
rf /= Void;
rf.base_feature = Current;
local
r: like runnable;
ct: TYPE;
do
assertion_collector.clear;
header_comment_memory.clear;
ct := rf.current_type;
ct.base_class.collect_for(code_ensure,rf.name);
r := runnable(assertion_collector,ct,rf);
if r /= Void then
!!Result.make_runnable(r,ct,rf);
Result.set_header_comment(header_comment_memory.item);
header_comment_memory.clear;
end;
end;
feature {NONE}
require_collector: ARRAY[E_REQUIRE] is
once
!!Result.make(1,10);
end;
assertion_collector: ARRAY[ASSERTION] is
once
!!Result.make(1,10);
end;
header_comment_memory: MEMO[COMMENT] is
once
!!Result;
end;
feature {BASE_CLASS}
collect_for(code: INTEGER) is
local
er: E_REQUIRE;
do
if code = code_require then
er := require_assertion;
if er /= Void then
if not require_collector.fast_has(er) then
require_collector.add_last(er);
end;
end;
else
check
code = code_ensure;
end;
if ensure_assertion /= Void then
header_comment_memory.set_item(ensure_assertion.header_comment);
ensure_assertion.add_into(assertion_collector);
end;
end;
end;
feature {NONE}
frozen pretty_print_names is
-- Print only the names of the feature.
local
i: INTEGER;
do
from
i := 1;
names.item(i).declaration_pretty_print;
i := i + 1;
until
i > names.count
loop
fmt.put_string(", ");
names.item(i).declaration_pretty_print;
i := i + 1;
end;
end;
pretty_print_arguments is
deferred
end;
make_e_feature(n: like names) is
require
n.count >= 1;
do
names := n;
ensure
names = n
end;
feature {FEATURE_CLAUSE}
add_into(fd: DICTIONARY[E_FEATURE,STRING]) is
-- Also check for multiple definitions.
local
i: INTEGER;
fn: FEATURE_NAME;
do
base_class := names.item(1).start_position.base_class;
from
i := 1;
until
i > names.count
loop
fn := names.item(i);
if fd.has(fn.to_key) then
fn := fd.at(fn.to_key).first_name;
eh.add_position(fn.start_position);
eh.add_position(names.item(i).start_position);
eh.error("Double definition of feature ");
eh.append(fn.to_string);
eh.error(fz_dot);
else
fd.put(Current,fn.to_key);
end;
i := i + 1;
end;
end;
feature {C_PRETTY_PRINTER}
stupid_switch(up_rf: RUN_FEATURE; r: ARRAY[RUN_CLASS]): BOOLEAN is
-- True when it is stupid do such a switch.
-- Assume all `base_feature' of `r' is Current.
require
run_control.boost;
small_eiffel.is_ready;
up_rf.base_feature = Current;
up_rf.run_class.running = r;
r.count >= 1
deferred
end;
feature {NONE}
try_to_undefine_aux(fn: FEATURE_NAME;
bc: BASE_CLASS): DEFERRED_ROUTINE is
require
fn /= Void;
bc /= Void
deferred
end;
em1: STRING is " Cannot inherit thoses features in "
feature {NONE}
frozen merge_header_comments(other: E_FEATURE) is
-- Falling down of the `header_comment' for command short.
do
if small_eiffel.short_flag then
if header_comment = Void then
header_comment := other.header_comment;
elseif other.header_comment = Void then
other.set_header_comment(header_comment);
end;
end;
end;
invariant
names /= Void;
end -- E_FEATURE